Part 1 of this pygtk tutorial stopped with a working toolbar and two place 
holders. Part 2 of this tutorial  extended this minimal UI with a list of
songs which was created using GTK ListView. Part 3 showed how to gain better control 
on ListView. Part 4 added some final polish to the UI and added an empty Preferences 
Dialog. This part of the tutorial will create the following preferences dialog:

To begin with, the preferences Dialog has to contain a gtk.Notebook, which is created with:
  notebook = gtk.Notebook()
In order to keep a well organized and readable code, the creation of the notebook instance is 
defined in a class method of PrefDialog and called in the init method of the class:
def insert_notebook(self):
    """
    demonstrate a gtk notebook 
    """
    notebook = gtk.Notebook()
...
def __init__(self, window):
    """
    initialize the preferences dialog
    """
    # title, parent, flags (0, for defaults), no buttons
    self.dialog = gtk.Dialog("Preferences", window, 0,
    (gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL, gtk.STOCK_OK, gtk.RESPONSE_OK))
    self.dialog.set_default_size(250, 300)
    # creat the notebook instance
    self.insert_notebook()
    response = self.dialog.show_all()
    response = self.dialog.run()
    if response == gtk.RESPONSE_OK:
        print "The OK button was clicked"
    elif response == gtk.RESPONSE_CANCEL:
        print "The Cancel button was clicked"
    self.dialog.destroy()
Right now, this code does not do much. It attaches the notebook instance to the vbox which was automatically
created inside the Dialog window. A notebook can have multiple pages, and each page in turn can have widgets 
attached to it with the packing method demonstrated before:
def insert_notebook(self):
    """
    demonstrate a gtk notebook 
    """
    notebook = gtk.Notebook()
    lables = []
    for page in ["General", "File Names", "Encode", "Advanced"]:
        # later, we can replace widget with a vbox, and then
        # the road is wide open to start packing other widgets inside it!
        widget = gtk.Label(page + " Inside")
        widget1 = gtk.Label("Second Label")
        vbox = gtk.VBox(False)
        vbox.pack_start(widget)
        vbox.pack_start(widget1)
        label = gtk.Label(page)
        notebook.append_page(vbox,label)
    self.dialog.vbox.pack_start(notebook)
The above method will create the following Preferences Dialog:

Download the complete code for the preferences dialog.
However, this notebook is still quite primitive. The widgets added are just text widgets and the notebook tabs titles are not given. To access a notebook's tab the following method can be used:
 # index is an integer, with N-1 representing the last page
 # e.g. for a notebook with 4 page, idx can be 0,1,2 or 3
 tab = notebook.get_nth_page(idx)
The setting the tab's label is done with:
 notebook.set_tab_label_text(tab, "some title you would like to choose")
Once a notebook page is direct accessible, it could also be manipulated, and widgets
can be directly attached to it. Below, a gtk.FileChooserButton is added to the first 
tab (General). The file choose button, is not directly added to the page. Rather, it is 
packed inside a VBox instance. Into the same VBox gtk.Alignment instance,  is also
attached. This gtk.Aligment contains a flushed left gtk.Label.
    general = notebook.get_nth_page(0)
    filechooserbox = gtk.VBox(False)
    alignment = gtk.Alignment(0,0)
    filechooserlabel = gtk.Label("Destination folder")
    alignment.add(filechooserlabel)
    filechooserbutton = gtk.FileChooserButton("Destination folder")
    filechooserbutton.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
    filechooserbox.pack_start(alignment)
    filechooserbox.pack_start(filechooserbutton)
    general.add(filechooserbox)
This addition to the method insert_notebook will create the following preferences Dialog:

Notice, that the new VBox and the gtk.FileChooserButton where added to the existing labels!
Download the complete code for the preferences dialog with a FileChooserButton.
The complete assembly of widgets, is then added with the following add_notebook method:
def insert_notebook(self):
    """
    populate the notebook with widgets.
    """
    notebook = gtk.Notebook()
    for idx, page in enumerate(["General", "File Names", "Encode",
        "Advanced"]):
        # later, we can replace widget with a vbox, and then
        # the road is wide open to start packing other widgets inside it!
        widget = gtk.Label(page + " Inside")
        widget1 = gtk.Label("Second Label")
        vbox = gtk.VBox(False)
        vbox.pack_start(widget)
        vbox.pack_start(widget1)
        label = gtk.Label(page)
        notebook.append_page(vbox)
        pg = notebook.get_nth_page(idx)
        notebook.set_tab_label_text(pg, page)
    # here is how one can access a single tab
    another_label = gtk.Label("Accessed")
    pg.add(another_label)
    # populate general tab with proper stuff
    generalpage = notebook.get_nth_page(0)
    generalvbox = gtk.VBox(False)
    alignment = gtk.Alignment(0,0)
    filechooserlabel = gtk.Label("Destination folder")
    #filechooserlabel.set_justify(gtk.JUSTIFY_LEFT)
    alignment.add(filechooserlabel)
    filechooserbutton = gtk.FileChooserButton("Destination folder")
    filechooserbutton.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
    generalvbox.pack_start(alignment, False, False, 0)
    generalvbox.pack_start(filechooserbutton, False, False, 0)
    generalpage.add(generalvbox)
    # add check button for making m3u playlist
    make_playlist = gtk.CheckButton("Create M3U playlist")
    # make default as true
    make_playlist.set_active(True)
    generalvbox.pack_start(make_playlist, False, False, 0)
    # add the cdrom drive entry inside an hbox
    hbox = gtk.HBox(False)
    cdrom_label = gtk.Label("CD-ROM device: ")
    cdrom = gtk.Entry(128)
    cdrom.set_tooltip_text("Default: /dev/cdrom\n"
                           "Other example: /dev/hdc\n"
                           "Other example: /dev/sr0")
    hbox.pack_start(cdrom_label, False, False, 0)
    hbox.pack_start(cdrom, False, False, 0)
    generalvbox.pack_start(hbox, False,False, 0)
    eject_cd = gtk.CheckButton("Eject disc when finished")
    generalvbox.pack_start(eject_cd, False,False, 0)
    self.dialog.vbox.pack_start(notebook)
This code will produces the following General notebook tab:

Again, the new widgets are all added to the previous labels, and the method becomes quite long and messy. 
This calls for some code clean up and reorganising. First, since all the pages (tabs) in the notebooks are
going to have at least one widget, it makes since to create them and attach a gtk.VBox to each. Further, 
since long methods are hard to follow, it makes since to separate all the code that adds widgets to the 
General page. This code should be migrated to it's own method, e.g. def General_Page(self). Customizing
other pages would be similarly done in extra methods, e.g. def FileNames(self) and so on.And Finally, since,
the notebook instance should be accessible to all the methods that customize the pages, it should become
an instance variable, e.g., instead of:
notebook = gtk.Notebook()
the notebook is created as:
self.notebook = gtk.Notebook()
And the complete method to create the notebook is now:
def insert_notebook(self):
    """
    create a notebook with 4 pages, each containing a gtk.VBox.
    """
    self.notebook = gtk.Notebook()
    for idx, page in enumerate(["General", "File Names", "Encode", 
        "Advanced"]):
        # later, we can replace widget with a vbox, and then
        # the road is wide open to start packing other widgets inside it!
        vbox = gtk.VBox(False)
        self.notebook.append_page(vbox)
        pg = self.notebook.get_nth_page(idx)
        self.notebook.set_tab_label_text(pg, page)
    self.set_general_page()
    self.dialog.vbox.pack_start(self.notebook)
the method set_general_page():
def set_general_page(self):
    """
    add widgets to the page General
    """    
    # populate general tab with proper stuff
    generalpage = self.notebook.get_nth_page(0)
    generalvbox = gtk.VBox(False)
    alignment = gtk.Alignment(0,0)
    filechooserlabel = gtk.Label("Destination folder")
    #filechooserlabel.set_justify(gtk.JUSTIFY_LEFT)
    alignment.add(filechooserlabel)
    filechooserbutton = gtk.FileChooserButton("Destination folder")
    filechooserbutton.set_action(gtk.FILE_CHOOSER_ACTION_SELECT_FOLDER)
    generalvbox.pack_start(alignment, False, False, 0)
    generalvbox.pack_start(filechooserbutton,  False, False, 0)
    generalpage.add(generalvbox)
    # add check button for making m3u playlist
    make_playlist = gtk.CheckButton("Create M3U playlist")
    # make default as true
    make_playlist.set_active(True)
    generalvbox.pack_start(make_playlist,  False, False, 0)
    # add the cdrom drive entry inside an hbox
    hbox = gtk.HBox(False)
    cdrom_label = gtk.Label("CD-ROM device: ")
    cdrom = gtk.Entry(128)
    cdrom.set_tooltip_text("Default: /dev/cdrom\n"
                           "Other example: /dev/hdc\n"
                           "Other example: /dev/sr0")
    hbox.pack_start(cdrom_label, False, False, 0)
    hbox.pack_start(cdrom, False, False, 0)
    generalvbox.pack_start(hbox, False,False, 0)
    eject_cd = gtk.CheckButton("Eject disc when finished")
    generalvbox.pack_start(eject_cd, False,False, 0)
The total length of the code is only a bit shorter. However, the code regarding the page General is completely
encapsulated inside it's own method, and is called via:
 self.set_general_page()
The notebook itself is created with four pages, each containing a gtk.VBox widget. This makes modifying 
other pages quite straight forward, but avoids a long and complicated method to create a fully functioning 
notebook rich with widgets. The complete code for this part, demonstrating a gtk.Notebook with
pages and embedded widget can be found in the git tag NotebookwithGeneral_Tab. 
The next tree pages of the notebook are still empty. However, in the original application asunder
they all contain gtk widget which I found a bit tricky to control (namely, gtk.Frame). Hence, these pages will be 
populated with these multiple gtk.Frame widgets in the next part of this tutorial, and for now, the Preferences Dialog
contains one page with the title General and looks like that:

Share this post: